%% Author: 77
%% Created: 2011-7-3
%% Description: TODO: Add description to meta_data_ops
-module(meta_data_ops).
-author(kanghua ).  
-email(kanghua151@msn.com).  
-date("2011.07.06").  
%%
%% Include files
%%
-include("meta_schema.hrl").
-include_lib("stdlib/include/qlc.hrl").

%%
%% Exported Functions
%%
%%-export([add_node_resource_item/7]).

-export([create_node_resource_table/0]).
-export([create_network_address_resource_table/0]).
-export([create_vm_resource_config_table/0]).
-export([create_vm_runtime_info_table/0]).

-export([add_network_address_resource/1]).
-export([start_vncport_resource/0]).
-export([add_node_resource/7]).
-export([drop_node_resource/1]).
-export([request_node_resource/2]).
-export([request_network_address_resource/0]).
-export([return_node_resource/3]).
-export([return_network_address_resource/2]).


-export([insert_vm_resource_config/6]).
-export([insert_vm_runtime_info/3]).
-export([get_vm_runtime_info/1]).
-export([get_node_status/1]).
-export([open_node_resource/1]).
-export([close_node_resource/1]).

%-export([add_vm_resource_config/5]).
%%
%% API Functions
%%
create_node_resource_table()->
   io:format("create node resource table  ~n",[]), %% debug info
   mnesia:stop(),
%mnesia:delete_schema([node()]),
%mnesia:create_schema([node()]),
   mnesia:start(),
   case mnesia:create_table(node_resource, [
		{type,set},									
        {disc_copies, []},
        {attributes, record_info(fields,node_resource)}
        ])  
   of
    {atomic,ok} ->
        io:format("create success ~n");
    {aborted,Reason}->
        io:format("error:~p~n",[Reason]),
        {aborted,Reason}
   end.

create_network_address_resource_table()->
  io:format("create network_address_resource table  ~n",[]), %% debug info
  mnesia:stop(),
  %mnesia:delete_schema([node()]),
  %mnesia:create_schema([node()]),
  mnesia:start(),
  case mnesia:create_table(network_address_resource, [
		{type,set},											  
        {disc_copies, [node()]},
        {attributes, record_info(fields,network_address_resource)}
        ])
  of 
    {atomic,ok} ->
        io:format("create success ~n");
    {aborted,Reason}->
        io:format("error:~p~n",[Reason]),
        {aborted,Reason}
  end.


create_vm_resource_config_table()->
   io:format("create vm_resource_config table  ~n",[]), %% debug info
   mnesia:stop(),
   %mnesia:delete_schema([node()]),
   %mnesia:create_schema([node()]),
   mnesia:start(),
   case mnesia:create_table(vm_resource_config, [
		{type,set},
        {disc_copies, [node()]},
        {attributes, record_info(fields,vm_resource_config)}
        ])
   of
	 {atomic,ok} ->
        io:format("create success ~n");
     {aborted,Reason}->
        io:format("error:~p~n",[Reason]),
        {aborted,Reason}
   end.
   %%mnesia:add_table_index(vm_resource_config,vm_id).

create_vm_runtime_info_table()->
   io:format("create vm_runtime_info table  ~n",[]), %% debug info
   io:format("create vm_resource_config table  ~n",[]), %% debug info
   mnesia:stop(),
   %mnesia:delete_schema([node()]),
   %mnesia:create_schema([node()]),
   mnesia:start(),
   case mnesia:create_table(vm_runtime_info, [
		{type,set},									  
        {disc_copies, [node()]},
        {attributes, record_info(fields,vm_runtime_info)}
        ])
   of 
	 {atomic,ok} ->
        io:format("create success");
     {aborted,Reason}->
        io:format("error:~p~n",[Reason]),
        {aborted,Reason}
   end.


add_network_address_resource(IpAddr) ->
%	MacAddr = os:cmd("bash /root/ECP/CloudMaster/priv/script/mac_address.sh"),
	MacAddr = mac_address:get_one_mac(IpAddr),
	Row = #network_address_resource{ip_addr = IpAddr, 
					 	 			mac_addr = MacAddr,
					 	 			is_free = true,
					 	 			create_timestamp = now_localtime()
								   },
	io:format("row ~p ~n",[Row]), %% debug info
	F = fun() ->
		mnesia:write(Row)
	end,
	case mnesia:transaction(F) of
		{atomic,_} ->
			ok;
		{aborted,Reason} ->
		    io:format("Reason ~p ~n",[Reason]),
		    false
    end.

start_vncport_resource() ->
	vncport:init().

add_node_resource(HostName,IpAddr,VcpuCount,TotalStorageSize,TotalMemorySize,CurFreeStorageSize,CurFreeMemorySize) ->
	Row = #node_resource{host_name = HostName, 
					 	 ip_addr = IpAddr,
					 	 cpu_count = VcpuCount,
					 	 total_storage_size = TotalStorageSize,
					 	 total_memory_size =  TotalMemorySize,
					 	 cur_free_storage_size = CurFreeStorageSize,
				     	 cur_free_memory_size =  CurFreeMemorySize,
						 status = normal,
					 	 create_timestamp = now_localtime(),
					 	 update_timestamp = now_localtime()},
	io:format("row ~p ~n",[Row]), %% debug info
	F = fun() ->
		mnesia:write(Row)
	end,
	case mnesia:transaction(F) of
		{atomic,_}->ok;
		{aborted,Reason} ->
		     io:format("Reason ~p ~n",[Reason]),
		     false
    end.

drop_node_resource(Node) ->
	Tab = node_resource,
	F = fun() ->
		mnesia:delete(Tab,Node)
	end,
	case mnesia:transaction(F) of
		{atomic,_}->ok;
		{aborted,Reason} ->
		     io:format("Reason ~p ~n",[Reason]),
		     false
    end.

close_node_resource(Node)->
    Host_name = Node,
	F = fun() ->
    	[P] = mnesia:wread({node_resource,Host_name}),
    	mnesia:write(P#node_resource{status=down})
    end,
    mnesia:transaction(F),
	case mnesia:transaction(F) of
		{atomic,_}->ok;
		{aborted,Reason} ->
		     io:format("Reason ~p ~n",[Reason]),
		     false
    end.

open_node_resource(Node)->
	Host_name = Node,
	F = fun() ->
    	[P] = mnesia:wread({node_resource,Host_name}),
    	mnesia:write(P#node_resource{status=normal})
    end,
    mnesia:transaction(F),
	case mnesia:transaction(F) of
		{atomic,_}->ok;
		{aborted,Reason} ->
		     io:format("Reason ~p ~n",[Reason]),
		     false
    end.

request_node_resource(Mem_Size,Store_Size) ->
	F = fun() ->
		MatchHead = #node_resource{host_name='$1',cur_free_memory_size='$2',cur_free_storage_size='$3',status=normal, _='_'},
		Guard1 = {'>', '$2', Mem_Size},
		Guard2 = {'>', '$3', Store_Size},
        Res = '$_',
    	{Results,Cont} = mnesia:select(node_resource,[{MatchHead, [Guard1,Guard2], [Res]}],1,write),
	 	io:format("select results ~p ~n",[Results]),
    	%Result = lists:nth(random:uniform(length(Results)),Results),
		Result = lists:nth(1,Results),
	 	io:format("select result ~p ~n",[Result]),
     	Free_Memory  = Result#node_resource.cur_free_memory_size - Mem_Size, 
	 	Free_Storage = Result#node_resource.cur_free_storage_size - Store_Size, 
	 	New = Result#node_resource{cur_free_memory_size=Free_Memory,cur_free_storage_size=Free_Storage},
     	io:format("new result ~p ~n",[New]),
	 	mnesia:write(New),
		Result#node_resource.host_name
     end,
	 case mnesia:transaction(F) of
		{atomic,Node}->Node;
		{aborted,Reason} ->
		     io:format("Reason ~p ~n",[Reason]),
		     false;
	    {atomic,'$end_of_table'} -> 
 			 io:format("table is empty"),
		     false
     end.

return_node_resource(Node,MemSize,StoreSize) ->
	ok.


request_network_address_resource() ->
	io:format("enter func request network ~n"), %% debug info
	F = fun() ->
%		MatchHead = #network_address_resource{ip_addr='$1',is_free=true, _='_'},
%	   	{Results,Cont} =  mnesia:select(network_address_resource,[{MatchHead,[],['$_']}],1,read),
		Q = qlc:q([E || E <- mnesia:table(network_address_resource),
					E#network_address_resource.is_free==true]),
		Results = qlc:e(Q),
		io:format("new results ~p ~n",[Results]),
		Result = lists:nth(1,Results),
		New = Result#network_address_resource{is_free=false},
     	io:format("new result ~p ~n",[Result]),
	 	mnesia:write(New),
		{Result#network_address_resource.ip_addr, Result#network_address_resource.mac_addr}
	end,
	case mnesia:transaction(F) of
		{atomic,{IpAddr,MacAddr}} ->
             {IpAddr,MacAddr};
		{aborted,Reason} ->
		     io:format("Reason ~p ~n",[Reason]),
		     false;
        {atomic,'$end_of_table'} -> 
 			 io:format("table is empty"),
		     false
    end.


return_network_address_resource(IpAddr,MacAddr) ->
	ok.

insert_vm_resource_config(VmId,VcpuCount,MemSize,DiskSize,IpAddr,MacAddr) ->
	io:format("vm resource config ! ~n"),
	Row = #vm_resource_config{vm_id = VmId, 
					 	 	  vcpu_count = VcpuCount,
							  mem_size = MemSize,
					 		  disk_size = DiskSize,
					 	 	  ip_address =  IpAddr,
					 	 	  mac_address = MacAddr,
					 		  update_timestamp = now_localtime()},
	io:format("row ~p ~n",[Row]), %% debug info
	F = fun() ->
		mnesia:write(Row)
	end,
	case mnesia:transaction(F) of
		{atomic,_}->ok;
		{aborted,Reason} ->
		     io:format("Reason ~p ~n",[Reason]),
		     false
	end.

drop_vm_resource_config(Vm_Id)->
	ok.


insert_vm_runtime_info(VmId,HostName,VMStatus)->
	io:format("insert_vm_runtime_info ! ~n"),
    Row = #vm_runtime_info{vm_id = VmId, 
					 	   host_name = HostName,
					 	   vm_status = VMStatus,
					 	   create_timestamp =0,
					 	   update_timestamp = now_localtime()},
	F = fun() ->
		mnesia:write(Row)
	end,
	case mnesia:transaction(F) of
		{atomic,_}->ok;
		{aborted,Reason} ->
		     io:format("Reason ~p ~n",[Reason]),
		     false
	end.

get_vm_runtime_info(OldVmId) ->
	VmId = atom_to_list(OldVmId),
	io:format("get_vm_runtime_info ! vmid is ~p ~n",  [VmId]),
    F = fun() ->
		Results = mnesia:read(vm_runtime_info,VmId),
		Result = lists:nth(1, Results)
	end,
	case mnesia:transaction(F) of
		{atomic,Result} ->
			 io:format("select result ~p ~n",[Result]),
             Result;
		{aborted,Reason} ->
		     io:format("Reason ~p ~n",[Reason]),
		     false;
		{atomic,'$end_of_table'} -> 
 			 io:format("table is empty"),
		     false
	end.

get_node_status(Node) ->
	io:format("get_node_status!~n"),
	F = fun() ->
	%%这一句是有问题的，要好好修改一下
		mnesia:read(node_resource, Node)
	end,
	case mnesia:transaction(F) of
		{atomic, Results} ->
			io:format("select result ~p ~n", [Results]),
			Results;
		{aborted, Reason} ->
			io:format("aborted Reason:~p~n", [Reason]),
			false;
		{atomic, '$end_of_table'} ->
			io:format("table is empty~n"),
			false
	end.


remove_vm_runtime_info()->
	ok.

update_vm_runtime_status()->
	ok.
	


%%
%% Local Functions
%%
now_localtime()->
	erlang:localtime().
